/*
 * ThreeByteRing.cpp
 *
 *  Created on: 29-Jun-2009
 *      Author: nrqm
 */

#include "ThreeByteRing.h"
#include <avr/io.h>

ThreeByteRing::ThreeByteRing() :
	size(0),
	head_index(-1),
	tail_index(-1)
{

}

void ThreeByteRing::Add(uint8_t value)
{
	if (head_index == -1 || tail_index == -1)
	{
		// The ring is empty
		head_index = 0;
		tail_index = 0;
	}
	else
	{
		// Increment the tail.  If it exceeds the bounds of the ring, wrap the tail around to the front.
		// If it hits the head, increment the head (and wrap it around if necessary).
		tail_index++;
		if (tail_index == 3)
		{
			tail_index = 0;
		}
		if (tail_index == head_index)
		{
			head_index++;
			if (head_index == 3)
			{
				head_index = 0;
			}
		}
	}
	ring[tail_index] = value;
	// update the size
	if (size == 3)
	{
		size = 1;
	}
	else
	{
		size++;
	}
}

uint8_t ThreeByteRing::Remove()
{
	uint8_t retval;
	if (head_index == -1 || tail_index == -1)
	{
		// The ring is empty.  TODO: error?
		return 0;
	}
	retval = ring[head_index];
	if (head_index == tail_index)
	{
		// There was just one item in the ring, so removing it will leave an empty ring.
		head_index = -1;
		tail_index = -1;
	}
	// Increment the head, and wrap it around if it exceeds the bounds of the ring.
	head_index++;
	if (head_index == 3)
	{
		head_index = 0;
	}
	// update the size
	size--;

	return retval;
}

uint8_t ThreeByteRing::Peek()
{
	if (head_index == -1 || tail_index == -1)
	{
		// TODO: error?
		return 0;
	}
	return ring[head_index];
}

uint8_t ThreeByteRing::Size()
{
	return size;
}
